﻿using System;
using System.Collections.Generic;

using Centido.Core;

namespace Centido.Management.ConsoleManager
{
    /// <summary>
    ///   An execution context of a console command.
    /// </summary>
    internal class CommandExecutionContext
    {
        /// <summary>
        ///   The management console.
        /// </summary>
        private ManagementConsole _managementConsole;

        /// <summary>
        ///   The command parameters.
        /// </summary>
        private readonly Dictionary<string, CommandParameter> _parameters
            = new Dictionary<string, CommandParameter>();


        /// <summary>
        ///   Gets or sets the current domain.
        /// </summary>
        public Domain CurrentDomain { get; set; }
        

        /// <summary>
        ///   Gets or sets the management console.
        /// </summary>
        public ManagementConsole ManagementConsole
        {
            get 
            { 
                return _managementConsole;
            }
            set 
            {
                if (value == null) throw new ArgumentNullException("value");
                
                _managementConsole = value;
            }
        }


        /// <summary>
        ///   Gets the list of console command parameters.
        /// </summary>
        public IEnumerable<CommandParameter> CommandParameters
        {
            get { return _parameters.Values; }
        }


        /// <summary>
        ///   Adds the specified console command parameter to the execution context.
        /// </summary>
        /// <param name="parameter">The console command parameter to be added.</param>
        /// <exception cref="ArgumentNullException">Thrown when the value of <paramref name="parameter"/> is null.</exception>
        public void AddCommandParameter(CommandParameter parameter)
        {
            if (parameter == null) 
                throw new ArgumentNullException("parameter");

            if (!_parameters.ContainsKey(parameter.Name))
                _parameters.Add(parameter.Name, parameter);
        }


        /// <summary>
        ///   Deletes the specified console command parameter from the execution context.
        /// </summary>
        /// <param name="parameter">The console command parameter to be deleted.</param>
        /// <exception cref="ArgumentNullException">Thrown when the value of <paramref name="parameter"/> is null.</exception>
        public void DeleteCommandParameter(CommandParameter parameter)
        {
            if (parameter == null)
                throw new ArgumentNullException("parameter");

            if (_parameters.ContainsKey(parameter.Name))
                _parameters.Remove(parameter.Name);
        }

        /// <summary>
        ///   Retrives a console command parameter with the specified name.
        /// </summary>
        /// <param name="parameterName">The console command parameter name.</param>
        /// <param name="parameterShortName">The console command parameter short name. </param>
        /// <exception cref="ArgumentNullException">Thrown when the value of <paramref name="parameterName"/> is null.</exception>
        /// <exception cref="ArgumentNullException">Thrown when the value of <paramref name="parameterShortName"/> is null.</exception>
        /// <returns>Returns a console command parameter with the specified name
        /// if there is one; otherwise, returns null.</returns>
        public CommandParameter GetParameterByName(string parameterName, string parameterShortName = "")
        {
            if (parameterName == null)
                throw new ArgumentNullException("parameterName");
            if (parameterShortName == null)
                throw new ArgumentNullException("parameterShortName");

            // Searching using the full parameter name
            var result = _parameters.ContainsKey(parameterName) ? _parameters[parameterName] : null;

            // If needed, searching using the short parameter name
            return result ?? (_parameters.ContainsKey(parameterShortName) ? _parameters[parameterShortName] : null);
        }


        /// <summary>
        ///   Checks that the console command execution context has
        /// a command parameter with the specified name (or the specified short name) and it has a not empty value.
        /// </summary>
        /// <param name="parameterName">The command parameter name.</param>
        /// <param name="parameterShortName">The command parameter short name. </param>
        /// <exception cref="ArgumentNullException">Thrown when the value of <paramref name="parameterName"/> is null.</exception>
        /// <exception cref="ArgumentNullException">Thrown when the value of <paramref name="parameterShortName"/> is null.</exception>
        /// <returns>Returns true if the console command execution context has
        /// a command parameter with the specified name and not empty value,
        /// otherwise, returns false.</returns>
        public bool ParameterValueIsNotEmpty(string parameterName, string parameterShortName = "")
        {
            if (parameterName == null)
                throw new ArgumentNullException("parameterName");
            if (parameterShortName == null)
                throw new ArgumentNullException("parameterShortName");

            var parameter = GetParameterByName(parameterName, parameterShortName);

            if (parameter == null) return false;

            return !string.IsNullOrEmpty(parameter.FirstValue);
        }


        /// <summary>
        ///   Retrieves the parameter value.
        /// </summary>
        /// <param name="parameterName">The parameter name.</param>
        /// <param name="parameterShortName">The parameter short name. </param>
        /// <exception cref="ArgumentNullException">Thrown when the value of <paramref name="parameterName"/> is null.</exception>
        /// <exception cref="ArgumentNullException">Thrown when the value of <paramref name="parameterShortName"/> is null.</exception>
        /// <returns>Returns the parameter value if the one with the specified name exists;
        /// otherwise, returns null.</returns>
        public string GetParameterValue(string parameterName, string parameterShortName = "")
        {
            if (parameterName == null)
                throw new ArgumentNullException("parameterName");
            if (parameterShortName == null)
                throw new ArgumentNullException("parameterShortName");

            var parameter = GetParameterByName(parameterName, parameterShortName);

            return parameter != null && !string.IsNullOrEmpty(parameter.FirstValue) ?
                parameter.FirstValue : null;
        }


        /// <summary>
        ///   Clears console command parameters list in the execution context.
        /// </summary>
        public void ClearCommandParameters()
        {
            _parameters.Clear();
        }
    }
}
